import datetime
import json
import threading
import time
import random

from paho import mqtt
from paho.mqtt import client as mqtt_client

from settings import settings
from logger import log

# broker = 'mq.wechain360.com'
port = 1883
# generate client ID with pub prefix randomly
client_id = f'webcam-{settings.code}-{random.randint(0, 1000)}'
client_obj = None
camera_offline_map = {}


def connect_mqtt():
    def on_connect(client, userdata, flags, rc, properties=None):
        if rc == 0:
            log.info("Connected to MQTT Broker! Client ID: %s", client_id)
        else:
            log.info("Failed to connect, return code %d\n", rc)

    def on_message(client, userdata, msg):
        try:
            # 解码消息并解析JSON数据
            json_data = json.loads(msg.payload)
        except ValueError:
            log.error("Invalid JSON message received")

    client = mqtt_client.Client(mqtt.enums.CallbackAPIVersion.VERSION2, client_id=client_id,
                                protocol=mqtt_client.MQTTv5)
    client.username_pw_set(settings.mqtt_username, settings.mqtt_password)
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect(settings.mqtt_server_uri, port)
    return client


def send_message(topic, message):
    if not client_obj:
        return
    client_obj.publish(topic, message, qos=0)


def add_offline_camera(name, rtsp):
    global camera_offline_map
    if name not in camera_offline_map:
        camera_offline_map[name] = {
            "name": name,
            "rtsp": rtsp,
            "offline": get_date_str(datetime.datetime.now())
        }


def remove_offline_camera(name):
    global camera_offline_map
    if name in camera_offline_map:
        camera_offline_map.pop(name)


def get_date_str(date):
    return date.strftime('%Y-%m-%d %H:%M:%S')


def online():
    def send_heartbeat():
        while True:
            # topic
            topic = "vs_node/" + settings.code + "/event/monitor"
            while True:
                time.sleep(1)
                content = {"online": True, "cameraOffline": list(camera_offline_map.values())}
                msg = json.dumps(content, ensure_ascii=False)
                result = client_obj.publish(topic, msg, qos=0)
                # result: [0, 1]
                status = result[0]
                if status != 0:
                    log.error(f"Failed to send message to topic {topic}")

    # Start the heartbeat in a new thread
    thread = threading.Thread(target=send_heartbeat)
    thread.start()


def init():
    global client_obj
    client_obj = connect_mqtt()
    client_obj.loop_start()
    online()


if __name__ == '__main__':
    init()
